package com.woniuxy.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.woniuxy.entity.dto.operations.ClientDetailDTO;
import com.woniuxy.entity.dto.operations.VehicleDisplayDTO;
import com.woniuxy.entity.po.operations.Vehicle;
import com.woniuxy.entity.po.operations.VehicleImg;
import com.woniuxy.mapper.ClientMapper;
import com.woniuxy.mapper.VehicleMapper;
import com.woniuxy.service.VehicleService;
import com.woniuxy.util.*;
import lombok.AllArgsConstructor;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @BelongsProject: charging-management-platform
 * @BelongsPackage: com.woniuxy.service
 * @Author: Quan
 * @Date: 2025/4/1 10:58
 */
@Service
//@AllArgsConstructor
@Transactional
public class VehicleServiceImpl implements VehicleService {
	@Resource
	private VehicleMapper vehicleMapper;
	@Resource
	private PageHelperUtil pageHelperUtil;
	@Resource
	private MinioUtils minioUtils;
	@Resource
	private ClientMapper clientMapper;
	@Resource
	private Redisson redisson;

	/**
	 * @Description: 根据条件查询，或者查询全部数据
	 * @Param: [vehicleDisplayDTO]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/1
	 */
	@Override
	public ResponseData<?> queryAll( PageParam<VehicleDisplayDTO> pageParam) {
		return ResponseData.ok(pageHelperUtil.getPageInfo(pageParam, vehicleMapper::queryAll, VehicleDisplayDTO::new));
	}

	/**
	 * @Description: 将图片添加到minio中，并且返回图片路径
	 * @Param: [file]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/1
	 */
	@Override
	public ResponseData<?> uploadImg(MultipartFile file) throws Exception {
		String imgPath = minioUtils.uploadFile(file);
		return ResponseData.ok(imgPath);
	}

	/**
	 * @Description: 将车辆添加到数据库中，同时将图片添加到图片数据库
	 * @Param: [vehicleDisplayDTO]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/1
	 */
	@Override
	public ResponseData<?> addVehicle(VehicleDisplayDTO vehicleDisplayDTO) {
		// 将车辆放入数据库，并返回对应的id
		vehicleMapper.addVehicle(vehicleDisplayDTO);
		// 将vehicleDisplayDTO中的images批量添加到vehicle_img中
		vehicleMapper.addBatchImgSrcToVehicleImg(vehicleDisplayDTO);
		return ResponseData.ok();
	}

	/**
	 * @Description: 通过车辆id查询车辆详情，并且将图片放在dto的images中
	 * @Param: [id]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/1
	 */
	@Override
	public ResponseData<?> queryById(Long id) {
		// 通过车辆id查询信息,
		VehicleDisplayDTO vehicleDisplayDTO = vehicleMapper.queryVehicleById(id);

		return ResponseData.ok(vehicleDisplayDTO);
	}

	/**
	 * @Description: 接收前端的vehicle数据，并同时更新到vehicle和vehicle_img中
	 * @Param: [vehicleDisplayDTO]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/1
	 * 1、将数据库中的图片和前端的图片地址进行比较，判断前端是否把图片进行了增加或者删除
	 * 2、判断车辆所属的用户是否发生了改变
	 * 		1、如果车辆发生改变，修改两位用户车辆的存储量
	 * 		2、如果没有发生改变，正常进行
	 * 要加分布式锁
	 */
	@Override
	public ResponseData<?> update(VehicleDisplayDTO vehicleDisplayDTO) {
		String lockName = "vehicleUpdateLock:" + vehicleDisplayDTO.getId();
		RLock lock = redisson.getLock(lockName);

		try {
			if (lock.tryLock(5, TimeUnit.SECONDS)) {
				//
				/*    对vehicle_img中进行的操作   */
				// 查询所有对应id的图片
				List<VehicleImg> vehicleImgs = vehicleMapper.queryVehicleImgByVehicleId(vehicleDisplayDTO.getId());
				// 获取前端对应的图片地址
				List<String> frontImgs = vehicleDisplayDTO.getImages();
				// 这里将数据库中的地址与前端传来的地址进行过滤，过滤掉与前端相同的地址，
				// 那么剩下的，即数据库中有但是前端没有的图片地址，即前端删除的图片地址
				List<Long> deleteImgIds = vehicleImgs.stream()
						.filter(vehicleImg -> !frontImgs.contains(vehicleImg.getImgSrc()))
						.map(VehicleImg::getId)
						.collect(Collectors.toList());
				// 这里将前端传来地址与数据库中的地址进行比较
				// noneMatch()表示流中没有任何元素满足给定条件
				// 也就是经过筛选后，得出来的是前端有而后端没有的数据，也就是新添加的数据
				List<String> newAddImgSrcs = frontImgs.stream()
						.filter(imgSrc ->
								vehicleImgs.stream()
										.noneMatch(vehicleImg -> vehicleImg.getImgSrc().equals(imgSrc)))
						.collect(Collectors.toList());
				// 对前端删除的数据进行删除操作
				if (!CollectionUtil.isEmpty(deleteImgIds)) {
					vehicleMapper.batchDelImgById(deleteImgIds);
				}
				// 对前端新增的数据进行批量添加
				if (!CollectionUtil.isEmpty(newAddImgSrcs)) {
					vehicleDisplayDTO.setImages(newAddImgSrcs);
					vehicleMapper.addBatchImgSrcToVehicleImg(vehicleDisplayDTO);
				}
				// 从数据库中根据id获取对应的vehicle实体类
				Vehicle vehicle = vehicleMapper.queryVehicleSimpleById(vehicleDisplayDTO.getId());
				/*   判断该车辆是否有持有人，如果之前没有持有人，则直接让对应持有人数量+1即可   */
				if (vehicle.getClientId() == null) {
					clientMapper.updateHoldCarNumById(vehicleDisplayDTO.getClientId(), 1);
				}

				/*   查询数据库中的车辆持有人和前端进行比较，判断该车辆是否发生改变   */
				// 根据车辆id查询该车辆持有人（即数据库中的持有人）和前端的持有人是否相同，如果不相同，则说明已经修改了，那么要对车辆的持有数进行更新
				if (vehicle.getClientId()!=null && !vehicle.getClientId().equals(vehicleDisplayDTO.getClientId())) {
					// 说明前端的用户改变了
					// 对vehicle数据库进行更新
					// 对旧持有人的车辆持有数-1
					clientMapper.updateHoldCarNumById(vehicle.getClientId(), -1);
					// 对新持有人的车辆持有数+1
					clientMapper.updateHoldCarNumById(vehicleDisplayDTO.getClientId(), 1);
				}

				/*    统一对vehicle数据库进行更新   */
				vehicleMapper.updateVehicle(vehicleDisplayDTO);
				return ResponseData.ok();
			} else {
				return ResponseData.fail(ResponseEnum.SYS_BUSY);  // 返回服务器繁忙
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (lock.isLocked() && lock.isHeldByCurrentThread()) {
				lock.unlock();
			}
		}
	}

	/**
	 * @Description: 通过前端传来的id与condition值修改数据库中的内容
	 * @Param: [vehicleDisplayDTO]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/2
	 */
	@Override
	public ResponseData<?> updateVehicleCondition(VehicleDisplayDTO vehicleDisplayDTO) {
		vehicleMapper.updateVehicleCondition(vehicleDisplayDTO);
		return ResponseData.ok();
	}

	@Override
	@Transactional
	public ResponseData<?> deleteById(Long id) {
		String lockName = "vehicleUpdateLock:" + id;
		RLock lock = redisson.getLock(lockName);
		try {
			if (lock.tryLock(5, TimeUnit.SECONDS)) {
				// 当获取到锁，进行逻辑删除操作
				vehicleMapper.deleteById(id);
				// 如果有对应的照片，对照片进行删除操作
				vehicleMapper.batchDelImgByVehicleId(id);
				return ResponseData.ok();
			} else {
				return ResponseData.fail(ResponseEnum.SYS_BUSY);
			}
		} catch (InterruptedException e) {
			throw new RuntimeException(e);
		} finally {
			if (lock.isLocked() && lock.isHeldByCurrentThread()) {
				lock.unlock();
			}
		}
	}

	/**
	 * @Description: 批量删除车以及相关联的图片
	 * @Param: [vehicleDisplayDTOList]
	 * @return: com.woniuxy.util.ResponseData<?>
	 * @Author: Quan
	 * @Date: 2025/4/2
	 */
	@Override
	public ResponseData<?> batchDelete(List<VehicleDisplayDTO> vehicleDisplayDTOList) {
		// 获取idList
		List<Long> ids = ListValueConvertUtils.listConvert(vehicleDisplayDTOList, VehicleDisplayDTO::getId);
		// 通过id进行批量的修改
		vehicleMapper.batchDelVehicleById(ids);
		// 通过vehicle批量修改img中数据
		vehicleMapper.batchDelImgByVehicleIdList(ids);
		return ResponseData.ok();
	}

}
